home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 727 / 2view / source / 2view.c next >
C/C++ Source or Header  |  1995-03-18  |  21KB  |  728 lines

  1.  
  2. /***********************************************************************\
  3. *                 2View V1.52                *
  4. *     A simple, fast ILBM viewer, for use under AmigaOS V2.x.    *
  5. *    Written and ©1991-1992 by Dave Schreiber.    All Rights Reserved.    *
  6. *                                    *
  7. * Usage:                                *
  8. *  2View FILE/A/M,FROM/K,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,PRINT    *
  9. *                                    *
  10. *  Where the following arguments are defined as follows:        *
  11. *   FILE - The name of one (or more) IFF ILBM files                     *
  12. *   FROM - A file containing a list of filenames.  Used instead of FILE *
  13. *   SECS - Number of seconds to display a file                *
  14. *   TICKS - Number of ticks (1/60ths of a second)                       *
  15. *   LOOP - When finished showing the last pictures, start over        *
  16. *   PRINT - Print each picture as it is shown                *
  17. *                                    *
  18. *  To compile (with SAS/C V5.10a):                                      *
  19. *     lc -v 2View ARexx                         *
  20. *     lc -v -b0 Misc                            *
  21. *     asm 2ViewAsm.a                            *
  22. *     blink with 2View.lnk                        *
  23. *                                    *
  24. *  Version history:                            *
  25. *     1.52 - Fixed a bug that would cause 2View to crash if it was    *
  26. *         given an ILBM of more than 8 bitplanes.            *
  27. *         Released on August 30, 1992                *
  28. *     1.51 - Added support for 2.0-style wildcards.            *
  29. *         Released on August 17, 1992                *
  30. *                                    *
  31. *     1.50 - Rewrote the subroutine that reads the ILBM from disk in    *
  32. *         assembly language, for speed.  Added support for SHAM and    *
  33. *         Macro Paint images, and for color cycling (both            *
  34. *         traditional (CRNG, i.e. continutout cycle ranges) and      *
  35. *         DPaint-IV style cycling (DRNG, i.e. non-continuous cycle   *
  36. *         ranges).  A 'tick' (as used with the "TICK" keyword, above)*
  37. *         has been redefined as 1/60th of a second.    Finally, the    *
  38. *         source code in 2View.c has been split into two files    *
  39. *         (2View.c and  Misc.c).                                     *
  40. *         Released 3/24/92                        *
  41. *                                    *
  42. *     1.11 - Improved error reporting (with this version, if the user   *
  43. *         run 2View from Workbench and there's an error, a requester *
  44. *         is put up.  Previously, the user was not notified at all    *
  45. *         of the error).                        *
  46. *         Released 9/11/91                        *
  47. *                                    *
  48. *     1.10 - Added support for Workbench, ARexx, scrollable bitmaps,    *
  49. *         and printing.  Also, the user can now use CTRL-C to advance*
  50. *         to the next frame, and CTRL-D to abort a playlist.     *
  51. *         Released 9/3/91                        *
  52. *                                    *
  53. *     1.00 - Original version.    Released 7/24/91            *
  54. *                                    *
  55. \************************************************************************/
  56.  
  57.  
  58. unsigned long availBytes,curPos,bufSize;
  59.  
  60. /*Include files*/
  61.  
  62. #include <exec/types.h>
  63. #include <libraries/iffparse.h>
  64. #include <dos/dos.h>
  65. #include <dos/dosasl.h>
  66. #include <intuition/intuition.h>
  67. #include <exec/memory.h>
  68. #include <workbench/startup.h>
  69. #include <graphics/gfxbase.h>
  70.  
  71. /*Prototypes*/
  72. #include <clib/exec_protos.h>
  73. #include <clib/intuition_protos.h>
  74. #include <clib/iffparse_protos.h>
  75.  
  76. /*Pragmas*/
  77. #include <pragmas/exec_pragmas.h>
  78. #include <pragmas/intuition_pragmas.h>
  79. #include <pragmas/graphics_pragmas.h>
  80. #include <pragmas/iffparse_pragmas.h>
  81. #include <pragmas/dos_pragmas.h>
  82.  
  83. /*Other include files*/
  84. #include "iff.h"
  85. #include "2View.h"
  86. #include "arexx.h"
  87.  
  88. /*Libraries we'll need*/
  89. struct Library *IFFParseBase=NULL;
  90. struct Library *IntuitionBase=NULL;
  91. struct GfxBase *GfxBase=NULL;
  92.  
  93. /*Provided by the compiler*/
  94. extern struct Library *SysBase;
  95. extern struct Library *DOSBase;
  96.  
  97. /*Generic screen and window definitions.  They will be used to define*/
  98. /*the screen and window that the various pictures will be shown on*/
  99. struct NewScreen newScreen=
  100. {
  101.    0,0,0,0,0,1,0,NULL,CUSTOMSCREEN|SCREENBEHIND|AUTOSCROLL,NULL,NULL,NULL,
  102.    NULL
  103. };
  104.  
  105. struct NewWindow newWindow =
  106. {
  107.    0,0,0,0,0,1,MENUDOWN|SELECTDOWN|ACTIVEWINDOW|VANILLAKEY,
  108.       RMBTRAP|BORDERLESS|NOCAREREFRESH,NULL,NULL,NULL,NULL,NULL,
  109.       0,0,640,400,CUSTOMSCREEN
  110. };
  111.  
  112. struct Screen *screen=NULL;
  113. struct Window *window=NULL;
  114.  
  115. /*------------------------------------------------------------------------*/
  116.  
  117. UWORD *storage;
  118. int counter;
  119.  
  120. /*A true here indicates the current ILBM file is compressed*/
  121. BYTE Compression;
  122.  
  123. /*An error message that used in various places*/
  124. char *errorMsg="An error occured while reading ";
  125.  
  126. /*The version string.  Do a 'version 2View' to display it*/
  127. char *version="$VER: QView V1.52 (30.8.92)";
  128.  
  129. /*Just so that the © message is part of the actual program*/
  130. char *copyRightMsg="Copyright 1991-1992 by Dave Schreiber.  All Rights Reserved.";
  131.  
  132. BYTE ExitFlag=FALSE;    /*'Exit now' flag*/
  133. UWORD ticks=0;          /*Delay requested by user.*/
  134.  
  135. /*The previous screen and window*/
  136. struct Window *prevWindow=NULL;
  137. struct Screen *prevScreen=NULL;
  138.  
  139. /*Data for a blank pointer*/
  140. UWORD chip fakePointerData[]={0,0,0,0,0};
  141.  
  142. struct IFFHandle *iff=NULL;   /*IFF handle*/
  143. BPTR pL=NULL;              /*Playlist file pointer*/
  144. BOOL masking,print,toFront,printPics;
  145. extern struct WBStartup *WBenchMsg;
  146.  
  147. char *playListFilename=NULL;
  148.  
  149. /*Variables that have to be global so that ARexx.c can access them*/
  150. ButtonTypes rexxAbort=none;
  151. extern void dispRexxPort(void);
  152. extern void dnRexxPort();
  153. long arexxSigBit;
  154. UWORD ticksRemaining=0;
  155. BOOL loop=FALSE;
  156. BYTE specialModes;
  157.  
  158. char *picFilename;
  159. char trashBuf[512];      /* A place to dump mask information */
  160. char *buf=trashBuf;
  161.  
  162. void _main();
  163.  
  164. struct TagItem TagList[]=
  165. {
  166.       /* This defines what part of the displayed picture is shown.  It's */
  167.       /* necessary to have a line like this in here in order to get     */
  168.       /* 2.0 autoscrolling to work.                     */
  169.    {SA_Overscan,OSCAN_VIDEO},
  170.    {TAG_DONE,NULL}
  171. };
  172.  
  173. char *about1="2View";
  174. char *about2="Please";
  175.  
  176. extern struct EasyStruct erError1Line;
  177. BOOL cycle=FALSE;
  178. UBYTE numColors;
  179. UWORD destMap[32];
  180. UBYTE numCycleColors;
  181. UBYTE rate;
  182.  
  183. /* The assembly-language reader routine */
  184. extern int  ReadIntoBitMapAsm(PLANEPTR,APTR,struct IFFHandle *,
  185.                   ULONG,ULONG,UWORD,UBYTE,UBYTE,UBYTE);
  186.  
  187. char **filenames;
  188. UWORD numFilenames=0,numSlots;
  189. struct AnchorPath *anchorPath=NULL;
  190.  
  191. /*------------------------------------------------------------------------*/
  192.  
  193. void _main()
  194. {
  195.    UWORD c;
  196.    LONG args[7];
  197.    char **filenames;
  198.    char curFilename[256];
  199.    BOOL playList; /*True if a playlist is being used, false otherwise*/
  200.    BYTE status=0;
  201.  
  202.       /*Allocate the pattern matching anchor*/
  203.    anchorPath=(struct AnchorPath *)
  204.                 AllocMem(sizeof(struct AnchorPath),MEMF_CLEAR);
  205.    if(anchorPath==NULL)
  206.       exit(99);
  207.  
  208.       /*Initialize the argument buffers to NULL*/
  209.    for(c=0;c<7;c++)
  210.       args[c]=NULL;
  211.  
  212.    openResources(args,&playList,&filenames);
  213.  
  214.       /*Run until we run out of filenames, or the user aborts*/
  215.    while(!ExitFlag)
  216.    {
  217.       picFilename=curFilename;     /*Get a pointer to the filename buffer*/
  218.  
  219.      /*Check to see if we're running from Workbench.  If so, and the*/
  220.      /*user provided names of pictures to display (by clicking on their*/
  221.      /*icons), display those pictures*/
  222.       if(WBenchMsg!=NULL && WBenchMsg->sm_NumArgs>1)
  223.       {
  224.      CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
  225.      picFilename=WBenchMsg->sm_ArgList[1].wa_Name;
  226.       }
  227.       else if(playList) /*If a playlist is being used*/
  228.       {
  229.      pL=Open(playListFilename,MODE_OLDFILE);   /*Open the playlist*/
  230.  
  231.      if(pL==NULL)   /*If we couldn't open the playlist, abort*/
  232.      {
  233.         printError("Can't open playlist","");
  234.         cleanup();
  235.         exit(199);
  236.      }
  237.  
  238.      do    /*Loop until we run out of playlist, or get a valid name*/
  239.      {
  240.         if(FGets(pL,picFilename,140)==NULL) /*If end-of-file*/
  241.            picFilename=NULL;       /*Set as NULL as a flag*/
  242.      }
  243.      while(picFilename!=NULL && picFilename[0]==0x0A);
  244.  
  245.      if(picFilename!=NULL)        /*If not NULL, it's a valid filename*/
  246.         picFilename[strlen(picFilename)-1]=NULL; /*Remove the linefeed*/
  247.       }
  248.       else  /*Otherwise, if a playlist isn't being used, get the current*/
  249.       {     /*filename*/
  250.      GetFilename(picFilename,filenames,anchorPath,&status);
  251.       }
  252.  
  253.      /*Loop while the user hasn't requested an abort, and while*/
  254.      /*there are still files to display*/
  255.       for(c=0;!ExitFlag && picFilename[0]!=NULL;c++)
  256.       {
  257.      if((iff->iff_Stream=Open(picFilename,MODE_OLDFILE))==NULL)
  258.      {     /*If the ILBM file can't be opened...*/
  259.  
  260.            /*Print an error...*/
  261.         printError("Can't open:  ", picFilename);
  262.  
  263.         cleanup();
  264.         exit(200);
  265.      }
  266.  
  267.      InitIFFasDOS(iff);      /*The IFF file will be read from disk*/
  268.  
  269.      OpenIFF(iff,IFFF_READ); /*Make iffparse.library aware of the*/
  270.                  /*ILBM file*/
  271.  
  272.      /*Read in the file and display*/
  273.      ReadAndDisplay(picFilename,iff);
  274.  
  275.      CloseIFF(iff);          /*Release iffparse's hold on the file*/
  276.  
  277.      Close(iff->iff_Stream); /*Close the file*/
  278.  
  279.         /*Get the next filename, either from Workbench,*/
  280.      if(WBenchMsg!=NULL)
  281.      {
  282.         if(WBenchMsg->sm_NumArgs > c+2)
  283.         {
  284.            CurrentDir(WBenchMsg->sm_ArgList[c+2].wa_Lock);
  285.            picFilename=WBenchMsg->sm_ArgList[c+2].wa_Name;
  286.         }
  287.         else
  288.            picFilename=NULL;
  289.      }
  290.      else if(playList)   /*The playlist*/
  291.      {
  292.         do
  293.         {
  294.            if(FGets(pL,picFilename,140)==NULL)
  295.           picFilename=NULL;
  296.         }
  297.         while(picFilename!=NULL && picFilename[0]==0x0A);
  298.  
  299.         if(picFilename!=NULL)
  300.            picFilename[strlen(picFilename)-1]=NULL;
  301.      }
  302.      else  /*or the command line*/
  303.         GetFilename(picFilename,filenames,anchorPath,&status);
  304.       }
  305.  
  306.      /*We're finished with this run of pictures*/
  307.       if(playList)         /*Close playlist, if open*/
  308.      Close(pL);
  309.       pL=NULL;
  310.  
  311.       if(!loop && !printPics) /*If the loop flag wasn't given, exit*/
  312.      ExitFlag=TRUE;
  313.    }
  314.  
  315.       /*Time to exit, so close stuff*/
  316.  
  317.    cleanup();
  318.    exit(0); /*And exit*/
  319. }
  320.  
  321. LONG ilbmprops[] = { ID_ILBM,ID_CMAP,ID_ILBM,ID_BMHD,ID_ILBM,ID_CAMG,
  322.              ID_ILBM,ID_CRNG,ID_ILBM,ID_DRNG,ID_ILBM,ID_SHAM,
  323.              ID_ILBM,ID_CTBL };
  324.  
  325. /*Read in an ILBM file and display it*/
  326. void ReadAndDisplay(char *filename,struct IFFHandle *iff)
  327. {
  328.    int error;
  329.    UBYTE *bodyBuffer;    /*Pointer to buffer holding 'BODY' chunk info*/
  330.    ULONG ViewModes;    /*Holds the viewmodes flags*/
  331.    UWORD c;
  332.    ButtonTypes button;
  333.    UBYTE cycleTable[32];
  334.    UBYTE countDown;
  335.  
  336.       /*Structures required for IFF parsing*/
  337.    struct StoredProperty *bmhd,*cmap,*camg,*crng,*drng,*sham,*ctbl;
  338.    struct ContextNode *bodyContext;
  339.  
  340.       /*IntuiMessage...*/
  341.    struct IntuiMessage *mesg;
  342.  
  343.       /*Indentify chunks that should be stored during parse*/
  344.       /*(in this case, CMAP, BMHD, CRNG, DRNG, CAMG, and SHAM)*/
  345.    error=PropChunks(iff,ilbmprops,7);
  346.  
  347.       /*If there was an error, print a message and return*/
  348.    if(error!=0)
  349.    {
  350.       printError(errorMsg,filename);
  351.       ExitFlag=TRUE;
  352.       return;
  353.    }
  354.  
  355.       /*Tell iffparse to stop at a 'BODY' chunk*/
  356.    error=StopChunk(iff,ID_ILBM,ID_BODY);
  357.  
  358.       /*Error handling yet again*/
  359.    if(error!=0 && error!=-1)
  360.    {
  361.       printError(errorMsg,filename);
  362.       ExitFlag=TRUE;
  363.       return;
  364.    }
  365.  
  366.       /*Do the actual parsing*/
  367.    error=ParseIFF(iff,IFFPARSE_SCAN);
  368.  
  369.       /*Check for errors yet again*/
  370.    if(error!=0 && error !=-1)
  371.    {
  372.       printError(errorMsg,filename);
  373.       ExitFlag=TRUE;
  374.       return;
  375.    }
  376.  
  377.       /*Get the chunks that were found in the file*/
  378.    bmhd = FindProp(iff,ID_ILBM,ID_BMHD);  /*Bitmap information*/
  379.    cmap = FindProp(iff,ID_ILBM,ID_CMAP);  /*Color map*/
  380.    camg = FindProp(iff,ID_ILBM,ID_CAMG);  /*Amiga viewmode information*/
  381.    crng = FindProp(iff,ID_ILBM,ID_CRNG);  /*Color-cycling ranges*/
  382.    drng = FindProp(iff,ID_ILBM,ID_DRNG);  /*New (DPaint IV) color-cycling*/
  383.    sham = FindProp(iff,ID_ILBM,ID_SHAM);  /*SHAM color tables*/
  384.    ctbl = FindProp(iff,ID_ILBM,ID_CTBL);  /*Macro Paint color table info*/
  385.  
  386.       /*Get the descriptor for the BODY chunk*/
  387.    bodyContext=CurrentChunk(iff);
  388.  
  389.       /*If there wasn't a BMHD, CMAP, or BODY chunk, abort*/
  390.    if(!bmhd | !cmap | !bodyContext)
  391.    {
  392.       printError(filename," is corrupted or is not in Amiga ILBM format");
  393.       ExitFlag=TRUE;
  394.       return;
  395.    }
  396.  
  397.       /*Prepare to determine screen modes*/
  398.    newScreen.ViewModes=NULL;
  399.  
  400.       /*If there was a CAMG chunk, use it to get the viewmodes*/
  401.    if(camg!=NULL)
  402.    {
  403.       ViewModes=( ((CAMG *)(camg->sp_Data))->viewmodes );
  404.  
  405.       if(ViewModes & HAM)
  406.      newScreen.ViewModes|=HAM;
  407.  
  408.       if(ViewModes & EXTRA_HALFBRITE)
  409.      newScreen.ViewModes|=EXTRA_HALFBRITE;
  410.  
  411.       if(ViewModes & LACE)
  412.      newScreen.ViewModes|=LACE;
  413.  
  414.       if(ViewModes & HIRES)
  415.      newScreen.ViewModes|=HIRES;
  416.    }
  417.  
  418.  
  419.    if(crng==NULL)
  420.       if(drng==NULL) /*No color cycling*/
  421.      numCycleColors=0;
  422.       else  /* DPaint-IV--style color cycling*/
  423.      numCycleColors=interpretDRNG(cycleTable,(DRNG *)(drng->sp_Data),&rate);
  424.    else  /*DPaint I-III--style color cycling*/
  425.       numCycleColors=interpretCRNG( cycleTable,(CRNG *)(crng->sp_Data),&rate);
  426.  
  427.    if(numCycleColors != 0)
  428.       cycle=TRUE;    /*Start cycling if there are colors to cycle*/
  429.    else
  430.       cycle=FALSE;
  431.  
  432.       /*Interpret the BMHD chunk*/
  433.    getBMHD((struct BitMapHeader *)bmhd->sp_Data);
  434.  
  435.    if(newScreen.Depth>8)
  436.    {
  437.       printError(filename," has more than 8 bitplanes");
  438.       ExitFlag=TRUE;
  439.       return;
  440.    }
  441.  
  442.       /*Don't open an interlace screen if the image is in SHAM mode*/
  443.       /*(the Amiga OS doesn't properly handle user copper lists on */
  444.       /*interlaced screens for some reason)*/
  445.    if(sham!=NULL)
  446.       newScreen.ViewModes&=~LACE;
  447.  
  448.       /*Open a screen, defined by the BMHD and CAMG chunks*/
  449.    screen=OpenScreenTagList(&newScreen,TagList);
  450.  
  451.       /*If the screen couldn't be opened, abort*/
  452.    if(screen==NULL)
  453.    {
  454.       printError("Cannot open screen!","");
  455.       ExitFlag=TRUE;
  456.       return;
  457.    }
  458.  
  459.       /*This more properly centers the screen, for some reason */
  460.    MoveScreen(screen,1,1);
  461.    MoveScreen(screen,-1,-1);
  462.  
  463.       /*Set the window dimensions from the screen dimensions*/
  464.    newWindow.Screen=screen;
  465.    newWindow.Width=newScreen.Width;
  466.    newWindow.Height=newScreen.Height;
  467.  
  468.       /*Open the window*/
  469.    window=OpenWindow(&newWindow);
  470.  
  471.       /*Abort if the window couldn't be opened*/
  472.    if(window==NULL)
  473.    {
  474.       printError("Cannot open window!","");
  475.  
  476.       ExitFlag=TRUE;
  477.       return;
  478.    }
  479.  
  480.       /*Allocate enough memory to hold the BODY data*/
  481.       /*We want to find out what the biggest block of memory is.  If*/
  482.       /*we have enough memory to hold the entire body chunk, we'll load*/
  483.       /*the whole thing into memory and decompress from there.    If not,*/
  484.       /*we'll load as much as we can and refill the buffer when it*/
  485.       /*empties*/
  486.       /*We do a Forbid() to keep anyone from allocating memory between*/
  487.       /*the AvailMem() and AllocMem() calls.  This way, we're guaranteed*/
  488.       /*that a memory block of the size given by Availmem() can be */
  489.       /*allocated.  For this reason, we don't need to check the result*/
  490.       /*of the AllocMem();  we're guaranteed that it worked*/
  491.    Forbid();
  492.    bufSize=AvailMem(MEMF_LARGEST);
  493.    bufSize=MIN(bufSize,bodyContext->cn_Size+1);
  494.    if(bufSize==0)    /*It'll never happen, but just in case...*/
  495.    {
  496.       Permit();
  497.       ExitFlag=TRUE;
  498.       return;
  499.    }
  500.  
  501.    bodyBuffer=AllocMem(bufSize,0L);
  502.    Permit();
  503.  
  504.    availBytes = bufSize;
  505.    curPos = bufSize;
  506.  
  507.       /*Blank out the pointer*/
  508.    SetPointer(window,fakePointerData,1,16,0,0);
  509.  
  510.       /*Set the screen colors to those provided in the CMAP chunk*/
  511.    setScreenColors(screen,cmap->sp_Data,newScreen.Depth,destMap,&numColors);
  512.  
  513.       /*Uncompress an ILBM and copy it into the bitmap*/
  514.    if(ReadIntoBitmapAsm(&(screen->BitMap.Planes),bodyBuffer,iff,bufSize,
  515.              (ULONG)screen->BitMap.BytesPerRow,
  516.              screen->BitMap.Rows,
  517.              screen->BitMap.Depth,(Compression==1) ? 1 : 0,
  518.              (masking) ? 1 : 0))
  519.    {
  520.       printError(errorMsg,"");
  521.       cleanup();
  522.       exit(2000);
  523.    }
  524.  
  525.  
  526.       /*Activate the window, and flush any IDCMP message*/
  527.    ActivateWindow(window);
  528.    while((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL)
  529.       ReplyMsg((struct Message *)mesg);
  530.  
  531.  
  532.       /*If this is a SHAM image, setup the copper list appropriately*/
  533.    if(sham!=NULL)
  534.    {
  535.       specialModes=SHAM;
  536.       setupSHAM(screen,(UWORD *)(sham->sp_Data));
  537.    }
  538.    else
  539.      /*If this is a MacroPaint image, setup the copper list*/
  540.       if(ctbl!=NULL)
  541.       {
  542.      specialModes=MACROPAINT;
  543.      setupDynHires(screen,(UWORD *)(ctbl->sp_Data));
  544.       }
  545.       else
  546.         /* Otherwise, this is a normal ILBM*/
  547.      specialModes=NORMAL;
  548.  
  549.       /*Bring the screen to the front*/
  550.    ScreenToFront(screen);
  551.  
  552.       /*If the user used the 'print' flag on the command line, print*/
  553.       /*the picture (but not if this is a SHAM or MacroPaint image)*/
  554.    if(printPics && specialModes == NORMAL)
  555.       dumpRastPort(&(screen->RastPort),&(screen->ViewPort));
  556.  
  557.    print=TRUE;
  558.  
  559.       /*Close the previous window and screen*/
  560.    if(prevWindow!=NULL)
  561.       CloseWindow(prevWindow);
  562.    if(prevScreen!=NULL)
  563.       CloseScreen(prevScreen);
  564.  
  565.       /*Free the buffer that holds the BODY chunk information*/
  566.    FreeMem(bodyBuffer,bufSize);
  567.  
  568.       /*Store the current window & screen structures, so they can be*/
  569.       /*closed later*/
  570.    prevWindow=window;
  571.    prevScreen=screen;
  572.  
  573.    screen=NULL;
  574.    window=NULL;
  575.  
  576.    rexxAbort=none;
  577.    countDown=rate;
  578.    if(ticks==0)   /*If ticks==0, this means that no delay was specified*/
  579.    {          /*by the user.  So just wait for him to click a button*/
  580.       int prevTopEdge=prevScreen->TopEdge;
  581.  
  582.       while((button=checkButton())==none && rexxAbort==none)
  583.       {
  584.         /*Wait for 1/60th of a second*/
  585.      WaitTOF();
  586.  
  587.         /*Refresh the SHAM copper list if required*/
  588.      if(prevTopEdge!=prevScreen->TopEdge && sham!=NULL)
  589.      {
  590.         prevTopEdge=prevScreen->TopEdge;
  591.         setupSHAM(prevScreen,(UWORD *)(sham->sp_Data));
  592.      }
  593.  
  594.         /*Refresh the MacroPaint copper list if required*?
  595.      if(prevTopEdge!=prevScreen->TopEdge && ctbl!=NULL)
  596.      {
  597.         prevTopEdge=prevScreen->TopEdge;
  598.         setupDynHires(prevScreen,(UWORD *)(ctbl->sp_Data));
  599.      }
  600.  
  601.         /*If its time to cycle the colors, then cycle them*/
  602.      if(cycle && numCycleColors!=0 && --countDown==0)
  603.      {
  604.         cycleColors(cycleTable,destMap,numCycleColors,numColors);
  605.         countDown=rate;
  606.      }
  607.      dispRexxPort();
  608.       }
  609.  
  610.      /*Check to see if the user wants to abort*/
  611.       if(button==menu || rexxAbort==menu)
  612.      ExitFlag=TRUE;
  613.    }
  614.    else     /*Otherwise, wait for the specified amount of time*/
  615.    {
  616.       for(c=0;c<ticks;c++)
  617.       {
  618.         /*Wait 1/60th of a second*/
  619.      WaitTOF();
  620.  
  621.         /*Cycle colors if necessary*/
  622.      if(cycle && numCycleColors!=0 && --countDown==0)
  623.      {
  624.         cycleColors(cycleTable,destMap,numCycleColors,numColors);
  625.         countDown=rate;
  626.      }
  627.  
  628.      dispRexxPort();         /*Check ARexx port*/
  629.  
  630.      button=checkButton();   /*After each 25 ticks, check to see if*/
  631.      if(button==menu || rexxAbort==menu)    /*the user wants to abort*/
  632.      {
  633.         ExitFlag=TRUE;
  634.         return;
  635.      }
  636.      if(button==select || rexxAbort==select)  /*Or advance prematurely*/
  637.         return;
  638.       }
  639.    }
  640. }
  641.  
  642. void GetFilename(char *picFilename,char **filenames,struct AnchorPath *anchor,
  643.          BYTE *status)
  644. {
  645.    int err=1;
  646.  
  647.    picFilename[0]=NULL;
  648.    if(*status==0)
  649.    {
  650.       while(err!=0 && filenames[*status]!=NULL)
  651.       {
  652.      err=MatchFirst(filenames[(*status)++],anchor);
  653.      if(err!=0 && !containsWildcards(filenames[(*status)-1]))
  654.      {
  655.         printError("Cannot open ",filenames[(*status)-1]);
  656.         cleanup();
  657.         exit(1000);
  658.      }
  659.       }
  660.       if(err!=0)
  661.      return;
  662.       else
  663.       {
  664.      NameFromLock(anchor->ap_Base->an_Lock,picFilename,256);
  665.      if(picFilename[strlen(picFilename)-1]!=':')
  666.         strcat(picFilename,"/");
  667.      strcat(picFilename,anchor->ap_Info.fib_FileName);
  668.      *status++;
  669.      return;
  670.       }
  671.  
  672.    }
  673.  
  674.    err=MatchNext(anchor);
  675.    if(err!=0)
  676.    {
  677.       MatchEnd(anchor);
  678.       while(err!=0 && filenames[*status]!=NULL)
  679.       {
  680.      if(err!=0 && !containsWildcards(filenames[(*status)-1]))
  681.      {
  682.         printError("Cannot open ",filenames[(*status)-1]);
  683.         cleanup();
  684.         exit(1010);
  685.      }
  686.      err=MatchFirst(filenames[(*status)++],anchor);
  687.       }
  688.       if(err!=0)
  689.      return;
  690.       else
  691.       {
  692.      NameFromLock(anchor->ap_Base->an_Lock,picFilename,256);
  693.      if(picFilename[strlen(picFilename)-1]!=':')
  694.         strcat(picFilename,"/");
  695.      strcat(picFilename,anchor->ap_Info.fib_FileName);
  696.      return;
  697.       }
  698.    }
  699.    else
  700.    {
  701.       NameFromLock(anchor->ap_Base->an_Lock,picFilename,256);
  702.       if(picFilename[strlen(picFilename)-1]!=':')
  703.      strcat(picFilename,"/");
  704.       strcat(picFilename,anchor->ap_Info.fib_FileName);
  705.       return;
  706.    }
  707. }
  708.  
  709. char tokens[]={'?','#','(','~','[','%','*'};
  710. #define NUMTOKENS (7)
  711.  
  712. /*Checks to see if a filename contains wildcard tokens (i.e. whether the*/
  713. /*given string is a filename or filepattern)*/
  714. BOOL containsWildcards(char *filename)
  715. {
  716.    int c,token;
  717.  
  718.    for(token=0;token<NUMTOKENS;token++)
  719.       for(c=0;filename[c]!=NULL;c++)
  720.      if(filename[c]==tokens[token])
  721.         return(TRUE);
  722.  
  723.    return(FALSE);
  724. }
  725.  
  726. /*End of 2View.c*/
  727.  
  728.